package com.gjy.util.encryption.signature;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.security.*;
import java.security.interfaces.DSAPrivateKey;
import java.security.interfaces.DSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

/**
 * SIGNATURE_ALGORITHM:
 * SHA1WithDSA, SHA224WithDSA, SHA384WithDSA, SHA512WithDSA
 *
 * @author 宫静雨
 * @version 1.0
 * @since 2022-11-07 15:27:26
 */
public class DSASignature {

    public DSASignature() {
        Security.addProvider(new BouncyCastleProvider());
        initKey();
    }

    // 数字签名，秘钥算法
    private static final String KEY_ALGORITHM = "DSA";
    // 数字签名，签名/验证算法
    private static final String SIGNATURE_ALGORITHM = "SHA512WithDSA";
    private static final String PUBLIC_KEY = "RSAPublicKey";
    private static final String PRIVATE_KEY = "RSAPrivateKey";
    // 512-1024，64的倍数
    private static final Integer KEY_SIZE = 512;
    private static final Map<String, Key> MAP = new HashMap<>(4);

    /**
     * 签名
     *
     * @param data 待签名数字
     * @return 数字签名
     */
    public byte[] sign(byte[] data) {
        try {
            // 转换私钥材料
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(MAP.get(PRIVATE_KEY).getEncoded());
            // 实例化秘钥工厂
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
            // 实例化Signature
            Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
            // 初始化
            signature.initSign(privateKey);
            // 更新
            signature.update(data);
            // 签名
            return signature.sign();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 校验
     *
     * @param data 待校验数据
     * @param sign 签名
     * @return 校验结果
     */
    public boolean verify(byte[] data, byte[] sign) {
        try {
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(MAP.get(PUBLIC_KEY).getEncoded());
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
            Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
            signature.initVerify(publicKey);
            signature.update(data);
            return signature.verify(sign);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 初始化秘钥
     */
    private void initKey() {
        try {
            // 实例化密钥对生成器
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
            keyPairGenerator.initialize(KEY_SIZE);
            // 生成密钥对
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            DSAPublicKey publicKey = (DSAPublicKey) keyPair.getPublic();
            DSAPrivateKey privateKey = (DSAPrivateKey) keyPair.getPrivate();
            MAP.put(PUBLIC_KEY, publicKey);
            MAP.put(PRIVATE_KEY, privateKey);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
